﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using System.IO;
using System.Management;
using System.Configuration;
using System.Collections;
using System.Web.Configuration;
using System.Collections.Specialized;

namespace AzureDriveExplorer_WebRole
{
    /// <summary>
    /// Summary description for WebService1
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class AzureDriveExplorerService : System.Web.Services.WebService
    {

        private long numPaketsDownload = 0;

        private long bLength = 0;

        private string driver = string.Empty;


        [WebMethod]
        public string[] getDirectory(string path, string keys)
        {
            string[] list = null;

            if (!keys.Equals(key()))
                return list;
            //// Use the storage emulator.
            //CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            ////CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=;AccountKey=");

            //// Create the Blob service client.
            //CloudBlobClient client = storageAccount.CreateCloudBlobClient();

            //// Create the container for the drive if it does not already exist.
            //CloudBlobContainer container = new CloudBlobContainer("mycontainer", client);
            //container.CreateIfNotExist();

            //// Get a reference to the page blob that will back the drive.
            //CloudPageBlob pageBlob = container.GetPageBlobReference("Test1");



            //// Return a reference to the drive backed by the specified page blob. 
            //CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
            //// Mount the drive.

            string driveLetter = string.Empty;
            try
            {
                //driveLetter = drive1.Mount(0, DriveMountOptions.None);
                //driver = driveLetter;

                list = System.IO.Directory.GetDirectories(path);

            }
            catch (Exception)
            {


            }

            return list;


        }

        [WebMethod]
        public string[] getFiles(string path, string keys)
        {
            string[] list = null;

            if (!keys.Equals(key()))
                return list;

            //// Use the storage emulator.
            //CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            ////CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=;AccountKey=");

            //// Create the Blob service client.
            //CloudBlobClient client = storageAccount.CreateCloudBlobClient();

            //// Create the container for the drive if it does not already exist.
            //CloudBlobContainer container = new CloudBlobContainer("mycontainer", client);
            //container.CreateIfNotExist();

            //// Get a reference to the page blob that will back the drive.
            //CloudPageBlob pageBlob = container.GetPageBlobReference("Test1");



            //// Return a reference to the drive backed by the specified page blob. 
            //CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
            //// Mount the drive.

            string driveLetter = string.Empty;
            try
            {
                //driveLetter = drive1.Mount(0, DriveMountOptions.None);
                //driver = driveLetter;

                list = System.IO.Directory.GetFiles(path);

            }
            catch (Exception)
            {


            }

            return list;


        }

        [WebMethod]
        public List<string> getVHD(string[] vecVHD, string keys)
        {
            
            List<string> list = new List<string>();

            //Validation
            if (!keys.Equals(key()))
                return list;


            for (int i = 0; i < vecVHD.Length; i++)
            {
                try
                {

                    string[] strvecHVD = vecVHD[i].Split(' ');

                    // Use the storage emulator.
                    CloudStorageAccount storageAccount = null;
                    //storageAccount = CloudStorageAccount.DevelopmentStorageAccount;

                    storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=" + strvecHVD[0] + ";AccountKey=" + strvecHVD[1]);
                    //storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=;AccountKey=");

                    // Create the Blob service client.
                    CloudBlobClient client = storageAccount.CreateCloudBlobClient();

                    // Create the container for the drive if it does not already exist.
                    //CloudBlobContainer container = new CloudBlobContainer("mycontainer", client);
                    CloudBlobContainer container = new CloudBlobContainer(strvecHVD[2], client);
                    //container.CreateIfNotExist();

                    // Get a reference to the page blob that will back the drive.
                    CloudPageBlob pageBlob = container.GetPageBlobReference(strvecHVD[3]);

                    // Return a reference to the drive backed by the specified page blob. 
                    CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
                    // Mount the drive.

                    //VHD Get Driver

                    bool ex = false;
                    foreach (var item in CloudDrive.GetMountedDrives())
                        if (item.Value.LocalPath.Equals(pageBlob.Uri.LocalPath))
                            ex = true;

                    if (!ex)
                    {
                        //ex = false;
                        string validate = drive1.Mount(0, DriveMountOptions.None);
                    }

                }
                catch (Exception)
                {
                }

            }


            //Get all Azure Drivers
            System.Management.ManagementObjectSearcher ms = new System.Management.ManagementObjectSearcher("SELECT * FROM win32_logicaldisk");
            foreach (ManagementObject mo in ms.Get())
            {

                list.Add(mo["deviceid"].ToString() + "\\");
            }

            return list;


        }

        [WebMethod]
        public bool setFile(byte[] file, string path, string name, string keys)
        {
            bool error = false;
            //Validation
            if (!keys.Equals(key()))
                return true;

            //string[] list = null;
            //// Use the storage emulator.
            //CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            ////CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=;AccountKey=");

            //// Create the Blob service client.
            //CloudBlobClient client = storageAccount.CreateCloudBlobClient();

            //// Create the container for the drive if it does not already exist.
            //CloudBlobContainer container = new CloudBlobContainer("mycontainer", client);
            //container.CreateIfNotExist();

            //// Get a reference to the page blob that will back the drive.
            //CloudPageBlob pageBlob = container.GetPageBlobReference("Test1");



            //// Return a reference to the drive backed by the specified page blob. 
            //CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
            //// Mount the drive.
            try
            {
                File.WriteAllBytes(path + name, file);
            }
            catch
            { error = true; }
            return error;
        }

        [WebMethod]
        public byte[] getFile(string path)
        {

            //// Use the storage emulator.
            //CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            ////CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=;AccountKey=");

            //// Create the Blob service client.
            //CloudBlobClient client = storageAccount.CreateCloudBlobClient();

            //// Create the container for the drive if it does not already exist.
            //CloudBlobContainer container = new CloudBlobContainer("mycontainer", client);
            //container.CreateIfNotExist();

            //// Get a reference to the page blob that will back the drive.
            //CloudPageBlob pageBlob = container.GetPageBlobReference("Test1");



            //// Return a reference to the drive backed by the specified page blob. 
            //CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
            //// Mount the drive.

            byte[] buffer = null;
            try
            {
                buffer = File.ReadAllBytes(path);
            }
            catch (Exception)
            {

            }

            return buffer;

        }

        [WebMethod]
        public bool CreateFile(string size, string path, string name)
        {
            bool error = false;
            //// Use the storage emulator.
            //CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            ////CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=;AccountKey=");

            //// Create the Blob service client.
            //CloudBlobClient client = storageAccount.CreateCloudBlobClient();

            //// Create the container for the drive if it does not already exist.
            //CloudBlobContainer container = new CloudBlobContainer("mycontainer", client);
            //container.CreateIfNotExist();

            //// Get a reference to the page blob that will back the drive.
            //CloudPageBlob pageBlob = container.GetPageBlobReference("Test1");



            //// Return a reference to the drive backed by the specified page blob. 
            //CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
            //// Mount the drive.

            byte[] buffer = new byte[long.Parse(size)];
            try
            {
                File.WriteAllBytes(path + name, buffer);
                //buffer = File.ReadAllBytes(path);
            }
            catch (Exception)
            {
                error = true;
            }

            return error;

        }

        [WebMethod]
        public bool DeleteFile(string path, string keys)
        {
            bool error = false;

            if (!keys.Equals(key()))
                return true;
            //// Use the storage emulator.
            //CloudStorageAccount storageAccount = null;

            //storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            ////storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=;AccountKey=");

            //// Create the Blob service client.
            //CloudBlobClient client = storageAccount.CreateCloudBlobClient();

            //// Create the container for the drive if it does not already exist.
            //CloudBlobContainer container = new CloudBlobContainer("mycontainer", client);
            //container.CreateIfNotExist();

            //// Get a reference to the page blob that will back the drive.
            //CloudPageBlob pageBlob = container.GetPageBlobReference("Test1");



            //// Return a reference to the drive backed by the specified page blob. 
            //CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
            //// Mount the drive.


            try
            {
                File.Delete(path);
                //buffer = File.ReadAllBytes(path);
            }
            catch (Exception)
            {
                error = true;
            }

            return error;

        }

        [WebMethod]
        public void newfile(string OutPath, byte[] paket, long beginner, long maxNumberbits)
        {
            decimal loop = decimal.Divide(beginner, maxNumberbits);

            File.WriteAllBytes(OutPath + "." + loop.ToString(), paket);
        }

        [WebMethod]
        public bool CreateFinishPaket(long file, string OutPath, long pakets)
        {
            bool error = false;
            try
            {
                byte[] b = new byte[file];
                //File.WriteAllBytes(OutPath, b);

                //byte[] outfile = new byte[file];
                long byteCount = 0;
                long byteCountCopy = 0;
                long count = 0;
                while (count < pakets)
                {
                    byte[] TempFile = ReadFile(OutPath + "." + count);

                    while (byteCountCopy < TempFile.Length)
                    {
                        b[byteCount] = TempFile[byteCountCopy];
                        byteCount++;
                        byteCountCopy++;
                    }
                    byteCountCopy = 0;
                    DeleteFile(OutPath + "." + count, key());
                    count++;
                }
                count = 0;
                while (count < pakets)
                {
                    File.Delete(OutPath + "." + count);
                    count++;
                }


                File.WriteAllBytes(OutPath, b);
            }
            catch { error = true; }
            return error;
        }

        /// <summary>
        /// 作ったファイルを削除します
        /// </summary>
        /// <param name="OutPath"></param>

        [WebMethod]
        public void Cancel(string OutPath)
        {
            long count = 0;
            bool finish = false;

            while (finish != true)
            {
                try
                {
                    if (File.Exists(OutPath + "." + count))
                        File.Delete(OutPath + "." + count);
                    else
                        finish = true;
                }
                catch
                {
                    finish = true;
                }
                count++;
            }

        }

        #region Download

        /// <summary>
        /// 選んだファイルを準備をしている、コピーしています。
        /// </summary>
        /// <param name="Inpath"></param>
        /// <returns></returns>
        [WebMethod]
        public string getCopyToDownload(string Inpath)
        {
            string pathout = string.Empty;
            try
            {
                string path = HttpContext.Current.Request.PhysicalApplicationPath;
                
                path += "Download\\";

                if (!Directory.Exists(@path))
                {
                    Directory.CreateDirectory(@path);
                }
                File.Copy(Inpath, path + LastNamePath(Inpath), true);

                if (File.Exists(path + LastNamePath(Inpath)))                    
                    pathout = HttpContext.Current.Request.Url.ToString().Replace(HttpContext.Current.Request.RawUrl, string.Empty) + "/Download/" + LastNamePath(Inpath);
                else 
                    pathout = "not exist this path " + path + LastNamePath(Inpath);
            }
            catch (Exception ex) { pathout = ex.Message; }
            return pathout;
        }

        /// <summary>
        /// urlのファイルを取ります
        /// </summary>
        /// <param name="Inpath"></param>
        /// <returns></returns>
        [WebMethod]
        public string getCopyURLDownload(string Inpath)
        {
            string pathout = string.Empty;
            try
            {
                string path = HttpContext.Current.Request.PhysicalApplicationPath;

                //path = path.Replace(HttpContext.Current.Request.FilePath.Replace("/", ""), "");
                path += "Download\\";
                if (File.Exists(path + LastNamePath(Inpath)))
                    pathout = HttpContext.Current.Request.Url.ToString().Replace(HttpContext.Current.Request.FilePath.Replace("/", ""), "") + "Download/" + LastNamePath(Inpath);
                else pathout = "not exist this path " + path + LastNamePath(Inpath);
            }
            catch (Exception ex) { pathout = ex.Message; }
            return pathout;
        }

        /// <summary>
        /// 終わってから、そのファイルを削除するようにします
        /// </summary>
        /// <param name="Inpath"></param>
        /// <returns></returns>
        [WebMethod]
        public bool getDeleteFileWeb(string Inpath)
        {
            bool deleted = false;
            try
            {
                string path = HttpContext.Current.Request.PhysicalApplicationPath;

                //path = path.Replace(HttpContext.Current.Request.FilePath.Replace("/", ""), "");
                path += "Download\\";
                File.Delete(path + LastNamePath(Inpath));
                deleted = true;
            }
            catch { }
            return deleted;
        }



        /// <summary>
        /// Testのために、こちらはダウンロードのときですが、まだよくないです
        /// </summary>
        /// <param name="Inpath"></param>
        /// <param name="MaxBit"></param>
        /// <returns></returns>
        [WebMethod]
        public string getFilePaket(string Inpath, long MaxBit)
        {

            string exe = string.Empty;

            //long numPakets = 0;
            bLength = 0;
            decimal loop = 0, count = 0;
            string outName = string.Empty;

            string path = string.Empty;
            try
            {


                byte[] file = File.ReadAllBytes(Inpath);
                //65536 bit is recomende for sending, in case send more bits, meaby lost the paket

                bLength = file.Length;

                byte[] sendPaket = new byte[MaxBit];

                byte[] addnewfile = null;
                //byte[] newfiles = new byte[b];
                //File.WriteAllBytes("d:\\1.rar", newfiles);

                path = FirstNamePath(Inpath);
                DateTime datetime = DateTime.Now;
                outName = LastNamePath(Inpath);// datetime.ToString("yyyyMMddHHmmss");

                loop = decimal.Divide(bLength, MaxBit);

                while (count < getWithOutDecimal(loop))
                {
                    addnewfile = getPaket(file, long.Parse((count * MaxBit).ToString()), MaxBit);
                    Getnewfile(path + "\\" + outName, addnewfile, (long)count, MaxBit);
                    count++;
                    numPaketsDownload++;
                }

                if (loop > count)
                {
                    long loopDecimal = long.Parse(count.ToString()) * MaxBit;
                    long countDecimal = 0;

                    //while (countDecimal < loopDecimal)
                    //{
                    addnewfile = getLastPaket(file, (long)loopDecimal, MaxBit);
                    Getnewfile(path + "\\" + outName, addnewfile, (long)count, MaxBit);
                    countDecimal++;
                    //}
                    numPaketsDownload++;
                }



            }
            catch (Exception ex) { exe += ex.Message; numPaketsDownload = 0; }


            return path + "\\" + outName + "-" + numPaketsDownload.ToString() + "-" + bLength.ToString() + "-" + loop.ToString() + "-" + exe;

        }

        [WebMethod]
        public string CreateFolder(string path, string keys)
        {
            if (!keys.Equals(key()))
                return "invalide certificate";

            string Messenger = string.Empty; ;
            try
            {
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);

                else
                    Messenger = "no";
            }
            catch (Exception ex)
            {
                Messenger = ex.Message;
            }

            return Messenger;
        }


        [WebMethod]
        public string DeleteFolder(string path, string keys)
        {

            if (!keys.Equals(key()))
                return "invalide certificate";


            string Messenger = string.Empty; ;
            try
            {
                if (Directory.Exists(path))
                    Directory.Delete(path);

                else
                    Messenger = "no";
            }
            catch (Exception ex)
            {
                Messenger = ex.Message;
            }

            return Messenger;
        }

        /// <summary>
        /// ひとつの部分をとります
        /// </summary>
        /// <param name="OutPath"></param>
        /// <param name="paket"></param>
        /// <param name="beginner"></param>
        /// <param name="maxNumberbits"></param>
        private void Getnewfile(string OutPath, byte[] paket, long beginner, long maxNumberbits)
        {
            //decimal loop = decimal.Divide(beginner, maxNumberbits);

            File.WriteAllBytes(OutPath + "." + beginner.ToString(), paket);
        }


        /// <summary>
        /// 残ったbytesを別のファイルを取っています
        /// </summary>
        /// <param name="file"></param>
        /// <param name="beginner"></param>
        /// <param name="maxNumberbits"></param>
        /// <returns></returns>
        protected byte[] getLastPaket(byte[] file, long beginner, long maxNumberbits)
        {
            byte[] paket = new byte[file.Length - beginner];
            long count = beginner, paketCount = 0;
            while (count < file.Length)
            {
                paket[paketCount] = file[count];
                paketCount++;
                count++;
            }
            return paket;

        }

        /// <summary>
        /// ファイルの部分をとります
        /// </summary>
        /// <param name="file"></param>
        /// <param name="beginner"></param>
        /// <param name="maxNumberbits"></param>
        /// <returns></returns>
        protected byte[] getPaket(byte[] file, long beginner, long maxNumberbits)
        {
            byte[] paket = new byte[maxNumberbits];
            long count = 0;
            while (count < maxNumberbits)
            {
                paket[count] = file[beginner + count];

                count++;
            }
            return paket;

        }
        #endregion


        /// <summary>
        /// ファイルを読んでいる、　bytes[]を戻る
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static byte[] ReadFile(string filePath)
        {
            byte[] buffer = null;
            try
            {
                buffer = File.ReadAllBytes(filePath);
            }
            catch
            {

            }

            return buffer;
        }

        /// <summary>
        /// 最後の部分を切り取り aa/bb/cc 結果=cc
        /// </summary>
        /// <param name="oldName"></param>
        /// <returns></returns>
        private string LastNamePath(string oldName)
        {
            string str_Name = string.Empty;
            string[] str_Split = oldName.Split('\\');
            for (int i = 0; i < str_Split.Length; i++)
                if (!str_Split[i].Equals(""))
                    str_Name = str_Split[i];

            return str_Name;

        }
        /// <summary>
        /// 最初の部分を切り取り aa/bb/cc 結果=aa
        /// </summary>
        /// <param name="oldName"></param>
        /// <returns></returns>
        private string FirstNamePath(string oldName)
        {
            string str_Name = string.Empty;
            string[] str_Split = oldName.Split('\\');
            for (int i = str_Split.Length - 1; i > -1; i--)
                if (!str_Split[i].Equals(""))
                    str_Name = str_Split[i];

            return str_Name;

        }

        /// <summary>
        /// integer をとります
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        private decimal getWithOutDecimal(decimal number)
        {
            decimal result = 0;
            try
            {
                string[] strNumber = number.ToString().Split('.');
                result = decimal.Parse(strNumber[0]);

            }
            catch { }
            return result;
        }

        [WebMethod]
        public string DeleteDriver(string AccountName, string AccountKey, string mycontainer, string name, string keys)
        {
            string error = string.Empty;

            if (!keys.Equals(key()))
                return "invalide certificate";

            try
            {
                // Use the storage emulator.
                CloudStorageAccount storageAccount = null;

                storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=" + AccountName + ";AccountKey=" + AccountKey);

                // Create the Blob service client.
                CloudBlobClient client = storageAccount.CreateCloudBlobClient();

                // Create the container for the drive if it does not already exist.
                CloudBlobContainer container = new CloudBlobContainer(mycontainer, client);

                // Get a reference to the page blob that will back the drive.
                CloudPageBlob pageBlob = container.GetPageBlobReference(name);

                // Return a reference to the drive backed by the specified page blob. 
                CloudDrive drive1 = new CloudDrive(pageBlob.Uri, storageAccount.Credentials);
                // Mount the drive.

                // Unmount the drive.
                drive1.Unmount();

                // Delete the drive.
                drive1.Delete();

            }
            catch (Exception ex)
            {
                error = ex.Message;

            }
            return error;
        }

        protected string key()
        {
            string key = string.Empty;
            key = RoleEnvironment.GetConfigurationSettingValue("Credential");
            return key;
        }
    }
}
